package requestProxy

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/sirupsen/logrus"
	"goproject/commonType"
	"goproject/logger"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
)

func parseLogLevel(line string) logrus.Level {
	if strings.Contains(line, "debug") {
		return logrus.DebugLevel
	}
	if strings.Contains(line, "info") {
		return logrus.InfoLevel
	}
	if strings.Contains(line, "warn") {
		return logrus.WarnLevel
	}
	if strings.Contains(line, "error") {
		return logrus.ErrorLevel
	}
	return logrus.InfoLevel // 默认返回 info 级别
}

// filterLogs 过滤指定级别的日志
func filterLogsByLevel(logs string, level logrus.Level) ([]string, error) {
	var filteredLogs []string
	lines := strings.Split(logs, "\n")

	// 定义日志行的正则表达式模式
	logPattern := regexp.MustCompile(`^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{6}Z\s+(debug|info|warn|error)\s+`)

	for _, line := range lines {
		if logPattern.MatchString(line) && parseLogLevel(line) == level {
			filteredLogs = append(filteredLogs, line)
		}
	}

	return filteredLogs, nil
}

/*
	func InitK8sClient() (*kubernetes.Clientset, error) {
		var config *rest.Config
		var err error

		// 尝试使用 InClusterConfig
		config, err = rest.InClusterConfig()
		if err != nil {
			log.Println("Failed to get in-cluster config, trying kubeconfig...")

			// 使用当前用户主目录下的 kubeconfig 文件路径
			kubeconfig := filepath.Join(os.Getenv("HOME"), ".kube", "config")
			log.Printf("Using kubeconfig: %s\n", kubeconfig)

			config, err = clientcmd.BuildConfigFromFlags("", kubeconfig)
			if err != nil {
				log.Printf("Failed to build config from kubeconfig: %v\n", err)
				return nil, err
			}
		} else {
			log.Println("Using in-cluster config")
		}

		// 创建 Clientset
		clientset, err := kubernetes.NewForConfig(config)
		if err != nil {
			log.Printf("Failed to create clientset: %v\n", err)
			return nil, err
		}

		log.Println("Successfully created clientset")
		return clientset, nil
	}
*/
func InitK8sClient() (*kubernetes.Clientset, error) {
	var config *rest.Config
	var err error

	// 检查是否在集群内部运行
	if _, inCluster := os.LookupEnv("KUBERNETES_SERVICE_HOST"); inCluster {
		log.Println("在集群内部运行，使用 in-cluster 配置...")
		config, err = rest.InClusterConfig()
		if err != nil {
			log.Printf("获取 in-cluster 配置时出错: %v\n", err)
			return nil, err
		}
	} else {
		log.Println("在本地运行，使用 kubeconfig 文件...")

		// 使用当前用户主目录下的 kubeconfig 文件路径
		kubeconfig := filepath.Join(os.Getenv("HOME"), ".kube", "config")
		log.Printf("使用 kubeconfig 文件: %s\n", kubeconfig)

		config, err = clientcmd.BuildConfigFromFlags("", kubeconfig)
		if err != nil {
			log.Printf("从 kubeconfig 构建配置时出错: %v\n", err)
			return nil, err
		}
	}

	// 创建 Clientset
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		log.Printf("创建 clientset 时出错: %v\n", err)
		return nil, err
	}

	log.Println("成功创建 clientset")
	return clientset, nil
}

// 根据podnames  与 namespace 以及 spanIdList 返回对应的请求数据
func GetRequestData(ctx context.Context, podInfoList []commonType.PodInfo, namespace string) ([]commonType.TraceRequestList, error) {
	log := logger.GetLogger()
	var traceRequestList []commonType.TraceRequestList

	for _, podInfo := range podInfoList {
		traceRequest, err := getTraceRequests(podInfo, namespace)
		if err != nil {
			log.Errorf("获取追踪请求时出错: %v", err)
			return nil, err
		}
		traceRequestList = append(traceRequestList, traceRequest)
	}

	return traceRequestList, nil
}

func getTraceRequests(podInfo commonType.PodInfo, namespace string) (commonType.TraceRequestList, error) {
	log := logger.GetLogger()
	clientset, err := InitK8sClient()
	if err != nil {
		log.Errorf("初始化K8s客户端时出错: %v", err)
		return commonType.TraceRequestList{}, err
	}

	logs, err := getFilteredLogs(clientset, podInfo.PodName, namespace, podInfo.SpanList)
	if err != nil {
		log.Errorf("获取过滤日志时出错: %v", err)
		return commonType.TraceRequestList{}, err
	}

	// 声明一个commonType.TraceRequestList
	traceRequestList := commonType.TraceRequestList{
		PodName:       podInfo.PodName,
		TraceRequests: nil,
	}
	for _, spanItem := range podInfo.SpanList {
		traceRequests := parseLogs(logs, spanItem)
		traceRequestList.TraceRequests = append(traceRequestList.TraceRequests, traceRequests...)
	}

	return traceRequestList, nil
}

func writeLogToFile(filePath string, logLine []string) error {
	file, err := os.OpenFile(filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		return err
	}
	defer file.Close()

	_, err = file.Write([]byte(strings.Join(logLine, "\n")))
	if err != nil {
		return err
	}

	return nil
}

func getFilteredLogs(clientset *kubernetes.Clientset, podName, namespace string, spanlist []string) ([]string, error) {
	cmd := exec.Command("kubectl", "exec", podName, "-n", namespace, "-c", "istio-proxy", "--", "curl", "-X", "POST", "http://127.0.0.1:15000/logging?level=debug")
	output, err := cmd.CombinedOutput()
	if err != nil {
		return nil, fmt.Errorf("执行命令时出错: %v, 输出: %s", err, string(output))
	}
	tailLines := int64(10000)
	log.Println("获取 pod 日志...")
	podLogs := clientset.CoreV1().Pods(namespace).GetLogs(podName, &corev1.PodLogOptions{
		Container: "istio-proxy",
		TailLines: &tailLines,
	})

	logStream, err := podLogs.Stream(context.Background())
	if err != nil {
		log.Printf("获取日志流时出错: %v\n", err)
		return nil, err
	}
	defer func() {
		log.Println("关闭日志流...")
		logStream.Close()
	}()
	// 获取当前项目的路径
	/*currentDir, err := os.Getwd()
	log.Println("当前项目的路径:", currentDir)
	filePath := currentDir + "/" + podName + ".log"
	scanner := bufio.NewScanner(logStream)
	for scanner.Scan() {
		logLine := scanner.Text()
		err := writeLogToFile(filePath, logLine)
		if err != nil {
			log.Printf("写入日志文件时出错: %v\n", err)
			return "", err
		}
	}

	if err := scanner.Err(); err != nil {
		return "", err
	}
	filterdLogsFirst, err := filterLogsByLevel(filePath, logrus.InfoLevel)
	if err != nil {
		return "", err
	}*/
	var logs strings.Builder
	buf := make([]byte, 8192)
	log.Println("读取日志流...")
	for {
		numBytes, err := logStream.Read(buf)
		if numBytes == 0 {
			break
		}
		if err != nil {
			log.Printf("读取日志时出错: %v\n", err)
			return nil, err
		}
		logs.Write(buf[:numBytes])
	}
	filteredLogsBylevel, _ := filterLogsByLevel(logs.String(), logrus.InfoLevel)
	log.Printf("podname: %s, spanId: %s", podName, spanlist)
	currentDir, err := os.Getwd()
	filePath := currentDir + "/logs/" + podName + ".log"
	err = writeLogToFile(filePath, filteredLogsBylevel)
	var filteredLogs []string
	log.Println("开始过滤日志...")
	for _, spanItem := range spanlist {
		filteredLogsTemp, err := filterLogs(podName, filteredLogsBylevel, spanItem)

		if err != nil {
			log.Printf("过滤日志时出错: %v\n", err)
			return nil, err
		}
		filteredLogs = append(filteredLogs, filteredLogsTemp...)
	}
	return filteredLogs, nil
}

func filterLogs(podName string, logs []string, spanItem string) ([]string, error) {
	var filteredLogs []string
	lines := append([]string{}, logs...)

	//infoRegex := regexp.MustCompile(`info`)
	spanRegex := regexp.MustCompile(fmt.Sprintf(`Headers.*%s`, spanItem))

	log.Printf("linelen: %d", len(lines))

	for i, line := range lines {
		if spanRegex.MatchString(line) {
			// filteredLogs = append(filteredLogs, line)
			start := i - 2
			if start < 0 {
				start = 0
			}
			end := i + 2
			if end > len(lines) {
				end = len(lines)
			}
			filteredLogs = append(filteredLogs, lines[start:end]...)
		}
	}

	//var targetFilterLogs []string
	//for _, line := range filteredLogs {
	//	if infoRegex.MatchString(line) {
	//		targetFilterLogs = append(targetFilterLogs, line)
	//	}
	//}
	//return strings.Join(targetFilterLogs, "\n"), nil
	return filteredLogs, nil
}

func parseLogs(logs []string, spanItem string) []commonType.Request {
	log := logger.GetLogger()
	log.Printf("targetLogs: %s", logs)
	var targetLogs []string
	// 首先得定位到目标logs的位置
	for i, lg := range logs {
		start := i - 2
		if start < 0 {
			start = 0
		}
		end := i + 2
		if end > len(logs) {
			end = len(logs)
		}
		if strings.Contains(lg, spanItem) {
			targetLogs = logs[start:end]
		}
	}

	var traceRequests []commonType.Request
	lines := targetLogs
	var currentTrace commonType.Request
	currentHeaders := make(map[string]interface{})
	var currentData map[string]interface{}

	reMethod := regexp.MustCompile(`Request Method:\s+(\S+)`)
	rePath := regexp.MustCompile(`Request Path:\s+(\S+)`)
	reHeaders := regexp.MustCompile(`Request Headers:\s+(.+)`)
	//reBody := regexp.MustCompile(`Raw Request Body:\s+(.+)`)
	reParsedJSON := regexp.MustCompile(`Raw Request Body:\s+({.*?})\s+thread=`)

	for _, line := range lines {
		if reMethod.MatchString(line) {
			currentTrace.Method = reMethod.FindStringSubmatch(line)[1]
		}
		if rePath.MatchString(line) {
			currentTrace.URL = rePath.FindStringSubmatch(line)[1]
		}
		if reHeaders.MatchString(line) {
			headers := reHeaders.FindStringSubmatch(line)[1]
			headersList := strings.Split(headers, ", ")
			for _, header := range headersList {
				parts := strings.Split(header, ": ")
				if len(parts) == 2 {
					if strings.Contains(parts[0], ":") {
						parts[0] = strings.Split(parts[0], ":")[1]
					}
					currentHeaders[parts[0]] = parts[1]
				}
			}
			currentTrace.Header = currentHeaders
		}
		if reParsedJSON.MatchString(line) {
			body := reParsedJSON.FindStringSubmatch(line)[1]
			json.Unmarshal([]byte(body), &currentData)
			currentTrace.Data = currentData
		}
	}
	traceRequests = append(traceRequests, currentTrace)
	currentTrace = commonType.Request{}
	currentHeaders = make(map[string]interface{})
	return traceRequests
}

func GetAllPods() error {
	clientset, err := InitK8sClient()
	// 获取所有命名空间中的 Pod 列表
	log.Println("获取所有命名空间中的 Pod 列表...")
	pods, err := clientset.CoreV1().Pods("").List(context.Background(), metav1.ListOptions{})
	if err != nil {
		return fmt.Errorf("获取 Pod 列表时出错: %v", err)
	}

	// 打印所有 Pod 的名称和命名空间
	for _, pod := range pods.Items {
		fmt.Printf("Pod 名称: %s, 命名空间: %s\n", pod.Name, pod.Namespace)
	}

	return nil
}
